using DevExpress.Blazor;
using EasyXaf.EntityDesigner.BusinessObjects.Entities;
using EasyXaf.EntityDesigner.Editors.DetailViewEditors.Models;
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;

namespace EasyXaf.EntityDesigner.Editors.DetailViewEditors.Components;

public partial class EntityTreeComponent : IAsyncDisposable
{
    private readonly string EntityTreeId = $"id-{Guid.NewGuid()}";

    private DotNetObjectReference<EntityTreeComponent> DotNetObjectRef { get; set; }

    private IJSObjectReference JsModule { get; set; }

    [Inject]
    private IJSRuntime JSRuntime { get; set; }

    private DxTreeView EntityTree { get; set; }

    private List<EntityTreeNode> Nodes { get; set; }

    [Parameter]
    public string CssClass { get; set; }

    [Parameter]
    public Entity Entity { get; set; }

    private async ValueTask InitSortableAsync()
    {
        if (JsModule != null)
        {
            await JsModule.InvokeVoidAsync("init", EntityTreeId, DotNetObjectRef);
        }
    }

    protected override void OnInitialized()
    {
        base.OnInitialized();

        Nodes = [new EntityTreeNode(Entity, null, null)];
    }

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        await base.OnAfterRenderAsync(firstRender);

        if (firstRender)
        {
            EntityTree.SetNodeExpanded(e =>
            {
                if (e.DataItem is EntityTreeNode root)
                {
                    if (root.ParentNode == null && root.EntityProperty == null)
                    {
                        return true;
                    }
                }
                return false;
            }, true);

            var jsModuleFile = "/Editors/DetailViewEditors/Components/EntityTreeComponent.razor.js";
            JsModule = await JSRuntime.InvokeAsync<IJSObjectReference>("import", jsModuleFile);
            DotNetObjectRef = DotNetObjectReference.Create(this);
            await InitSortableAsync();
        }
    }

    public async ValueTask DisposeAsync()
    {
        try
        {
            if (JsModule != null)
            {
                await JsModule.InvokeVoidAsync("dispose", DotNetObjectRef);
            }
        }
        catch (JSDisconnectedException)
        {
        }

        if (JsModule != null)
        {
            await JsModule.DisposeAsync();
            JsModule = null;
        }

        DotNetObjectRef?.Dispose();
        DotNetObjectRef = null;

        GC.SuppressFinalize(this);
    }
}